package com.xinhe.web.service;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.xinhe.web.common.Result;
import com.xinhe.web.entity.*;
import com.xinhe.web.reposity.AddressRepository;
import com.xinhe.web.reposity.OrderItemRepository;
import com.xinhe.web.request.ShopCartModel;
import com.xinhe.web.response.ShopCartGoodsView;
import com.xinhe.web.response.ShopCartView;
import com.xinhe.web.response.TeamBuyOrderView;
import com.xinhe.web.session.UserSessionManager;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.inject.Provider;
import javax.persistence.EntityManager;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class ShopcartService {
    @Autowired
    private UserSessionManager userSessionManager;
    @Autowired
    private AddressRepository addressRepository;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private OrderItemRepository orderItemRepository;
    //查询工厂
    private JPAQueryFactory queryFactory;
    @Autowired
    private Provider<EntityManager> entityManager;
    @PostConstruct
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }

    @Transactional
    public void saveShopcart(ShopCartModel model) {
        this.orderItemService.saveGoodsOrderItem(model,"SHOP_CART");
    }

    @Transactional
    public Result saveShopcartAmount(Integer amount, Long orderItemId) {
        if (0 >= amount) {
            this.orderItemRepository.deleteById(orderItemId);
        } else {
            OrderItem orderItem = this.orderItemRepository.findById(orderItemId).get();
            orderItem.setGoodsAmount(amount);
            orderItem.setItemPrice(orderItem.getGoodsPrice().multiply(new BigDecimal(orderItem.getGoodsAmount().intValue())));
            this.orderItemRepository.saveAndFlush(orderItem);
        }
        return Result.ok();
    }

    public Result findShopcart() {
        List<ShopCartGoodsView> shopcartGoodsViews = this.findForShopcart(this.userSessionManager.getUserId());
        return Result.ok(convertOrderItemView(shopcartGoodsViews));
    }

    public Result countShopcart() {
        List<ShopCartGoodsView> shopcartGoodsViews = this.findForShopcart(this.userSessionManager.getUserId());
        Integer count = Integer.valueOf(0);
        if (CollectionUtils.isNotEmpty(shopcartGoodsViews)) {
            for (ShopCartGoodsView shopcartGoodsView : shopcartGoodsViews) {
                count = Integer.valueOf(count.intValue() + shopcartGoodsView.getGoodsAmount().intValue());
            }
        }
        return Result.ok(Integer.valueOf((shopcartGoodsViews == null) ? 0 : count.intValue()));
    }
    public List<ShopCartGoodsView> findForShopcart(Long userId) {
        QOrderItem qOrderItem = QOrderItem.orderItem;
        QGoods qGoods = QGoods.goods;
        QGoodsPrice qGoodsPrice = QGoodsPrice.goodsPrice;
        QSellerShop qSellerShop = QSellerShop.sellerShop;
        BooleanBuilder builder = new BooleanBuilder();
        //builder.and(qTeamBuy.removed.eq(0));
        builder.and(qOrderItem.userId.eq(userId));
        builder.and(qOrderItem.status.eq("SHOP_CART"));
        return queryFactory.select(
                        Projections.bean(
                                ShopCartGoodsView.class,
                                qOrderItem.id.as("orderItemId"),
                                qOrderItem.userId,
                                qOrderItem.goodsId,
                                qOrderItem.goodsAmount,
                                qOrderItem.orderId,
                                qOrderItem.status,
                                qOrderItem.zoneType,
                                qGoods.name.as("goodsName"),
                                qGoods.iconPath.as("goodsIconPath"),
                                qGoods.price.as("goodsPrice"),
                                qSellerShop.fUserId.as("goodsSellerUserId"),
                                qSellerShop.name.as("goodsSellerName")
                        )
                ).from(qOrderItem)
                .leftJoin(qGoods).on(qOrderItem.goodsId.eq(qGoods.id))
                .leftJoin(qGoodsPrice).on(qOrderItem.goodsPriceId.eq(qGoodsPrice.id))
                .leftJoin(qSellerShop).on(qGoods.sellerUserId.eq(qSellerShop.fUserId))
                .where(builder).fetch();
    }

    public Result findForSubmit(Set<Long> orderItemIds) {
        List<ShopCartGoodsView> shopCartGoodsViews = this.findForList(orderItemIds);
        List<ShopCartView> views = convertOrderItemView(shopCartGoodsViews);
        return Result.ok(views);
    }
    public List<ShopCartGoodsView> findForList(Set<Long> orderItemIds) {
        QOrderItem qOrderItem = QOrderItem.orderItem;
        QGoods qGoods = QGoods.goods;
        QGoodsPrice qGoodsPrice = QGoodsPrice.goodsPrice;
        QSellerShop qSellerShop = QSellerShop.sellerShop;
        BooleanBuilder builder = new BooleanBuilder();
        //builder.and(qTeamBuy.removed.eq(0));
        builder.and(qOrderItem.id.in(orderItemIds));
        return queryFactory.select(
                        Projections.bean(
                                ShopCartGoodsView.class,
                                qOrderItem.id.as("orderItemId"),
                                qOrderItem.userId,
                                qOrderItem.goodsId,
                                qOrderItem.goodsAmount,
                                qOrderItem.orderId,
                                qOrderItem.status,
                                qOrderItem.zoneType,
                                qGoods.name.as("goodsName"),
                                qGoods.iconPath.as("goodsIconPath"),
                                qGoods.price.as("goodsPrice"),
                                qSellerShop.fUserId.as("goodsSellerUserId"),
                                qSellerShop.name.as("goodsSellerName")
                        )
                ).from(qOrderItem)
                .leftJoin(qGoods).on(qOrderItem.goodsId.eq(qGoods.id))
                .leftJoin(qGoodsPrice).on(qOrderItem.goodsPriceId.eq(qGoodsPrice.id))
                .leftJoin(qSellerShop).on(qGoods.sellerUserId.eq(qSellerShop.fUserId))
                .where(builder).fetch();
    }

    public void deleteShopcart(Set<Long> orderItemIds) {
        for (Long orderItemId :orderItemIds){
            this.orderItemRepository.deleteById(orderItemId);
        }
    }

    private List<ShopCartView> convertOrderItemView(List<ShopCartGoodsView> shopCartGoodsViews) {
        List<ShopCartView> views = new ArrayList<>();
        Map<Long, List<ShopCartGoodsView>> map = (Map<Long, List<ShopCartGoodsView>>)shopCartGoodsViews.stream().collect(Collectors.groupingBy(ShopCartGoodsView::getGoodsSellerUserId));
        for (Map.Entry<Long, List<ShopCartGoodsView>> entry : map.entrySet()) {
            ShopCartView view = new ShopCartView();
            view.setSellerUserId(entry.getKey());
            view.setSellerName(((ShopCartGoodsView)((List<ShopCartGoodsView>)entry.getValue()).get(0)).getGoodsSellerName());
            List<ShopCartGoodsView> shopCartGoodsViewList = entry.getValue();
            BigDecimal sumFee = BigDecimal.ZERO;
            int amount = 0;
            for (ShopCartGoodsView shopCartGoodsView : shopCartGoodsViewList) {
                amount += shopCartGoodsView.getGoodsAmount().intValue();
                sumFee = sumFee.add(shopCartGoodsView.getGoodsPrice().multiply(new BigDecimal(shopCartGoodsView.getGoodsAmount().intValue())));
            }
            view.setSumFee(sumFee.setScale(2, 1));
            view.setAmount(Integer.valueOf(amount));
            view.setOrderItems(shopCartGoodsViewList);
            views.add(view);
        }

        return views;
    }

    @Transactional
    public Result saveBuyNow(ShopCartModel model) {
        OrderItem orderItem = this.orderItemService.saveGoodsOrderItem(model,"SAVED");
        return Result.ok(orderItem.getId());
    }

}
